package com.zym.framework.progress;

import com.zym.framework.dialog.FxDialog;
import com.zym.framework.utlis.AppUtlis;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.StageStyle;
import javafx.stage.Window;

import java.text.DecimalFormat;

import static com.zym.framework.LayoutHelper.hbox;
import static com.zym.framework.LayoutHelper.vbox;
import static javafx.stage.WindowEvent.WINDOW_SHOWN;

/**
 * QQ 165149324
 * 臧英明
 *
 * @author
 * @create 2021-01-30
 */
public   class ProgressUtils {
    public static final DecimalFormat FORMAT = new DecimalFormat("#.00%");
    private  ProgressTask progressTask;

    private  Window owner;

    private final Label messageLabel = new Label();

    private final Label progressLabel = new Label();

    private boolean showAsPercentage = true;

    private boolean decorated = true;


    public static ProgressUtils create(Window owner, ProgressTask progressTask, String message) {
        return new ProgressUtils(owner, progressTask, message);
    }

    private ProgressUtils(Window owner, ProgressTask progressTask, String message) {
        this.owner = owner;
        this.progressTask = progressTask;
        progressTask.updateMessage(message);
    }

    public void setDecorated(boolean decorated) {
        this.decorated = decorated;
    }

    public void setShowAsPercentage(boolean showAsPercentage) {
        this.showAsPercentage = showAsPercentage;
    }

    public void show() {
        show0(false);
    }

    public void showAndWait() {
        show0(true);
    }

    private void show0(boolean wait) {
        Service<Void> service = new Service<Void>() {
            @Override
            protected Task<Void> createTask() {
                return progressTask;
            }
        };

        FxDialog<Void> fxDialog = new FxDialog<Void>()
                .setOwner(owner)
                .setTitle("请等待……")
                .setBody(progressBody(progressTask))
                .setButtonTypes(ButtonType.CANCEL)
                .setButtonHandler(ButtonType.CANCEL, (event, stage) -> service.cancel())
                .setCloseable(false)
                .withStage(stage -> {
                    if (!decorated) {
                        stage.initStyle(StageStyle.UNDECORATED);
                        stage.initModality(Modality.APPLICATION_MODAL);
                    }
                    stage.addEventHandler(WINDOW_SHOWN, event -> service.start());
                    service.setOnSucceeded(event -> stage.close());
                    service.setOnCancelled(event -> stage.close());
                    service.setOnFailed(event -> stage.close());
                });

        if (wait) {
            fxDialog.showAndWait();
        } else {
            fxDialog.show();
        }
    }

    private Parent progressBody(ProgressTask progressTask) {
        ProgressBar progressBar = new ProgressBar();
        progressBar.setPrefHeight(25);
        progressBar.setPrefWidth(300);

        progressTask.progressProperty().addListener(
                (observable, oldValue, newValue) -> updateProgress(progressTask, progressBar, progressLabel)
        );

        messageLabel.textProperty().bind(progressTask.messageProperty());

        return vbox(0, 5, Pos.CENTER,
                hbox(5, 0, messageLabel),
                new StackPane(progressBar, progressLabel)
        );
    }

    private void updateProgress(ProgressTask progressTask, ProgressBar progressBar, Label progressLabel) {
        AppUtlis.runLater(() -> {
            double progress = progressTask.getProgress();
            progressBar.setProgress(progress);
            if (showAsPercentage) {
                progressLabel.setText(FORMAT.format(progress));
            } else {
                if (progressTask.getTotalWork() <= 1) {
                    progressLabel.setText(
                            String.format("%f / %f", progressTask.getWorkDone(), progressTask.getTotalWork())
                    );
                } else {
                    progressLabel.setText(
                            String.format("%d / %d", (int) progressTask.getWorkDone(), (int) progressTask.getTotalWork())
                    );
                }
            }
        });
    }

}
